package helper

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"git.inedcn.com/ined/cmn"
	"net/url"
	constant "rongyy/src/constants"
	"rongyy/src/models"
)

func Decrypt(str string) ([]byte, error) {
	ciphertext, _ := hex.DecodeString(str)
	pkey := PaddingLeft([]byte(constant.CryptoKey), '0', 16) //和js的key补码方法一致

	block, err := aes.NewCipher(pkey) //选择加密算法
	if err != nil {
		return nil, fmt.Errorf("key 长度必须 16/24/32长度: %s", err)
	}
	blockModel := cipher.NewCBCDecrypter(block, pkey) //和前端代码对应:   mode: CryptoJS.mode.CBC,// CBC算法
	plantText := make([]byte, len(ciphertext))
	blockModel.CryptBlocks(plantText, ciphertext)
	plantText = PKCS7UnPadding(plantText) //和前端代码对应:  padding: CryptoJS.pad.Pkcs7
	return plantText, nil
}

func PKCS7UnPadding(plantText []byte) []byte {
	length := len(plantText)
	unpadding := int(plantText[length-1])
	return plantText[:(length - unpadding)]
}

// 这个方案必须和js的方法是一样的
func PaddingLeft(ori []byte, pad byte, length int) []byte {
	if len(ori) >= length {
		return ori[:length]
	}
	pads := bytes.Repeat([]byte{pad}, length-len(ori))
	return append(pads, ori...)
}

// 明文补码算法
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

func Sm2Encrypto(str, pubkey string) (string, error) {
	data, err := PostJson(cmn.GetEnv("CRYPT_URL")+"/sm2/encrypt?appSecret="+str+"&pubKey="+pubkey, nil)
	if err != nil {
		return "", nil
	}
	rsp := &models.Sm2EncryptResp{}
	err = json.Unmarshal(data, rsp)
	return rsp.RespData, nil
}

func Sm2EncryptoTest(str, pubkey string) (*models.Sm2EncryptResp, error) {
	uri := cmn.GetEnv("CRYPT_URL") + "/sm2/encrypt?appSecret=" + url.QueryEscape(str) + "&pubKey=" + pubkey
	fmt.Println("uri====", uri)
	data, err := PostJson(uri, nil)
	fmt.Println(data)
	fmt.Println(err)
	if err != nil {
		return nil, err
	}

	rsp := &models.Sm2EncryptResp{}
	err = json.Unmarshal(data, rsp)
	return rsp, nil
}

func Sm4Encrypto(req *models.Sm4EncryptReq) (string, error) {
	data, err := PostJson(cmn.GetEnv("CRYPT_URL")+"/sm4/encrypt?token="+req.Token, req.Info)
	if err != nil {
		return "", nil
	}
	rsp := &models.Sm2EncryptResp{}
	err = json.Unmarshal(data, rsp)
	return rsp.RespData, nil
}

func Sm4Decrypto(req *models.Sm4DecryptReq) (*models.Sm4DecryptResp, error) {
	data, err := PostJson(cmn.GetEnv("CRYPT_URL")+"/sm4/decrypt?token="+req.Token+"&biz="+req.Biz, nil)
	if err != nil {
		return nil, err
	}
	rsp := &models.Sm4DecryptResp{}
	err = json.Unmarshal(data, rsp)
	return rsp, nil
}

func YktSm2Encrypto(req *models.YktSm2aEncryptoReq) (string, error) {
	data, err := PostJson(cmn.GetEnv("YKT_CRYPT_URL")+"/encrypt", req)
	if err != nil {
		return "", nil
	}
	//rsp := &models.Sm2EncryptResp{}
	//err = json.Unmarshal(data, rsp)
	//return rsp.RespData, nil
	return string(data), nil
}

func YktSm2Decrypto(req *models.YktSm4DecryptoReq) (string, error) {
	data, err := PostJson(cmn.GetEnv("YKT_CRYPT_URL")+"/decrypt", req)
	if err != nil {
		return "", nil
	}
	//rsp := &models.Sm2EncryptResp{}
	//err = json.Unmarshal(data, rsp)
	//return rsp.RespData, nil
	return string(data), nil
}

func YktSignEncrypto(req *models.YktSm2EncryptoReq) (string, error) {
	data, err := PostJson(cmn.GetEnv("YKT_CRYPT_URL")+"/sm2Sign", req)
	if err != nil {
		return "", nil
	}
	//rsp := &models.Sm2EncryptResp{}
	//err = json.Unmarshal(data, rsp)
	//return rsp.RespData, nil
	return string(data), nil
}
